— 1 min read
JSON Schema is a declarative language that allows you to annotate and validate JSON documents.
(annotate: 주석을 달다 / validate: 검증하다)
⇒ 말그대로 JSON에 대한 스키마이며, 항목들을 설명하고 검증하는데에 사용된다.
{ id: “34”, … }
다. 이걸 어떻게 바라봐야할까? 늘 문자열인가? 혹시 잘못 보낸건 아닐까? 파싱을 String으로 받도록 했는데 어느날 Integer로 오면 어떻게 처리를 해야할까? 이런 문제들을 해결하고자 명확하게 스키마를 통해 데이터에 대한 구조를 명시적으로 약속하여 데이터의 품질을 보장할 수 있다.그럼 어떻게 생겼는지 살펴보자.
1{2 "productId": 1,3}
1{2 "$schema": "https://json-schema.org/draft/2020-12/schema",3 "$id": "https://example.com/product.schema.json",4 "title": "Product",5 "description": "A product from Acme's catalog",6 "type": "object",7 "properties": {8 "productId": {9 "description": "The unique identifier for a product",10 "type": "integer",11 "exclusiveMinimum": 112 }13 },14 "required": [ "productId" ]15}
$schema
필드는 json-schema의 표준 중 어떤 버전의 draft를 쓰는지를 나타낸다.$id
필드는 이 스키마가 있는 uri를 정의한다.title
, description
은 문서화를 위한 필드.properties
필드 안에서 프로퍼티에 대한 상세한 정의를 나타낼 수 있다. 타입, 필수값인지의 여부, 해당 필드가 가질 수 있는 최소값 등등.스키마를 원래의 json document에 포함시켜야한다는건지, 따로 보낸다는건지? 가 궁금했는데, 스키마를 특정 URI에 올려놓고 사용하는 방식이었다. 공식 사이트에 있는 예시 URI를 보면 금방 이해가 된다. https://json-schema.org/learn/examples/calendar.schema.json
JSON Schema is hypermedia ready, and ideal for annotating your existing JSON-based HTTP API. JSON Schema documents are identified by URIs, which can be used in HTTP Link headers, and inside JSON Schema documents to allow recursive definitions.
+) kafka로 통신할때는 confluent의 schema registry를 사용하면 될 것 같다. producer는 registry에 스키마를 업로드해두고, consumer는 registry를 통해 얻은 스키마에 따라 데이터를 해석하는 방법.
공식문서에 안내된 구현체들은 언어별로 꽤 많다.
Java 프로젝트에 사용할 예정이라 다 클릭해보고 찾아본 결과:
요 두가지 중 하나를 쓰면 되지 않을까 싶다.
다른 구현체에 비해 고성능이라고 주장하는 최신 릴리즈의 networknt/json-schema-validator 를 간단히 테스트 해봤다. quick-start 문서를 참고했다.
1@Test2public void test() throws IOException {3 JsonNode schemaNode = getJsonNodeFromStringContent(4 "{\"$schema\": \"http://json-schema.org/draft-06/schema#\", \"properties\": { \"id\": {\"type\": \"number\"}}}");5 JsonSchema schema = getJsonSchemaFromJsonNodeAutomaticVersion(schemaNode);67 schema.initializeValidators();89 JsonNode node = getJsonNodeFromStringContent("{\"id\": \"2\"}");10 Set<ValidationMessage> errors = schema.validate(node);11 assertEquals(1, errors.size());12}131415protected JsonNode getJsonNodeFromStringContent(String content) throws IOException {16 return mapper.readTree(content);17}1819protected JsonSchema getJsonSchemaFromJsonNodeAutomaticVersion(JsonNode jsonNode) {20 JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersionDetector.detect(jsonNode));21 return factory.getSchema(jsonNode);22}
⇒ 테스트 통과. id의 타입은 number이기 때문에 errors에 ValidationMessage가 생긴다.
id 타입을 number로 바꿔주면 errors는 빈 set이 된다.:
1@Test2public void test() throws IOException {3 JsonNode schemaNode = getJsonNodeFromStringContent(4 "{\"$schema\": \"http://json-schema.org/draft-06/schema#\", \"properties\": { \"id\": {\"type\": \"number\"}}}");5 JsonSchema schema = getJsonSchemaFromJsonNodeAutomaticVersion(schemaNode);67 schema.initializeValidators();89 // JsonNode node = getJsonNodeFromStringContent("{\"id\": \"2\"}");10 // Set<ValidationMessage> errors = schema.validate(node);11 // assertEquals(1, errors.size());12 JsonNode node = getJsonNodeFromStringContent("{\"id\": 2 }");13 Set<ValidationMessage> errors = schema.validate(node);14 assertEquals(0, errors.size());15}